#include "app_device.h"
#include "app_buffer.h"
#include <fcntl.h>
#include "log.h"
#include "app_pool.h"
#include "app_message.h"
#include "app_mqtt.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "app_common.h"
#include <stdio.h>

app_device_t *device;


/**
 * @brief 上行线路2 ： 线程池要从缓冲区读取数据 发送给mqtt (异步)
 * 1 从缓冲区读取数据    app_buffer
 * 2 把数据转换为json   app_message
 * 3 发送给消息队列  app_mqtt
 */
void *app_device_buffer_to_mqtt(void *)
{   
    //  * 1 从缓冲区读取数据    app_buffer
    char buff[100];
    int read_data_size= app_buffer_read(device->up_buffer,buff,100);
    // * 2 把数据转换为json   app_message
    char *json=  app_message_bytes_to_json  (buff,read_data_size);
    // * 3 发送给消息队列  app_mqtt
    app_mqtt_send(json , strlen(json));
    return NULL;

}

// 上行线路 1： 启动对串口文件的读取  开辟线程 持续对串口文件执行read
//  异步函数 
// 1  读取串口文件 read 
// 2  对读取到的数据进行预处理转换  post_read
// 3  写入到上行缓冲区
// 4  将之后的操作以 函数指针的方式提交给线程池
void *app_device_up_read_dev(void *arg)
{
    char buff[100];
    while(1){
        // 1  读取串口文件 read 
        int read_size=read(device->fd,buff,100);
        if(read_size>0){
            printf("读取到数据:");
            app_common_print_hex(buff,read_size);
        }

        if(read_size>0 && device->post_read!=NULL)
        {// 2  对读取到的数据进行预处理转换  post_read
            read_size=  device->post_read(buff,read_size); //对数据转换后产生新的长度
        }
        if(read_size>0)
        {//// 3  写入到上行缓冲区
            
           int ret=  app_buffer_write(device->up_buffer,buff,read_size);
           if(ret<0)
           {
               log_error("app_buffer_write error\n");
               continue;
           }

         // 4  将之后的操作以 函数指针的方式提交给线程池
         app_pool_submit_task(app_device_buffer_to_mqtt,NULL);
            
        }

    }
    return NULL;

}

/**
 *  下行线路 2(图中4) ： 从 下行缓冲区中读取数据写入设备文件
 * 
 * 1  从缓冲区读取数据
 * 2  经过写前预处理an函数
 * 3  写入到设备文件
 */
void *app_device_down_buff_to_dev(void *arg)
{
    char buff[100];
    
     // 1  从下行缓冲区读取数据
    int read_data_size= app_buffer_read(device->down_buffer,buff,100);
   // 2  经过写前预处理函数
    if(read_data_size>0 && device->pre_write!=NULL)
    {
        read_data_size=device->pre_write(buff,read_data_size);
    }
    printf("要写入到数据长度:%d\n",read_data_size);
    if(read_data_size>0)
    {
        log_info("要写入到数据:");
        app_common_print_hex(buff,read_data_size);
    }

    //3 写入到设备文件
    write(device->fd,buff,read_data_size);

    return NULL;
}
/**
 *  下行线路 1(图中3) ： 接收mqtt收到的数据 发送到下行缓冲区中
 * 
 * 1  接收mqtt收到的数据 对数据进行转换 json->字节数组
 * 2  写入到下行缓冲区
 * 3  向线程池提交后续的任务 (异步)
 */

int app_device_down_mqtt_to_buffer(char *data,int data_size)
{

    // * 1  接收mqtt收到的数据 对数据进行转换 json->字节数组
    char buff[100];
    data_size=app_message_json_to_bytes(data,buff,100);

    // * 2  写入到下行缓冲区
    app_buffer_write(device->down_buffer,buff,data_size);

    // * 3  向线程池提交后续的任务 (异步)
    app_pool_submit_task(app_device_down_buff_to_dev,NULL);

    return 0;

}


/**
 * 初始化设备 
 */
app_device_t *app_device_init()
{
     device=(app_device_t *)malloc(sizeof(app_device_t));

     device->dev_file_name=DEVICE_FILE_NAME;
     device->fd=open(device->dev_file_name,O_RDWR);// 打开设备文件

     device->up_buffer=app_buffer_init();//上行
     device->down_buffer=app_buffer_init();//下行

     device->is_running=0;
     device->read_thread=-1;
     device->post_read=NULL;
     device->pre_write=NULL;

     device->last_write_ts=0;
     device->write_interval_ms=100;
    
     return device;
}



/**
 * 启动设备运行
 *  
 *  1 启动上行线路  启动对串口文件的读取  开辟线程 持续对串口文件执行read (拉模式)
 *  2 启动下行线路  启动对mqtt的读取   向消息队列模块注册真实的回调函数 （推模式）
 * 3 改变状态 is_running=1
 */
int app_device_start()
{   
    // 0 检查执行状态
    if(device->is_running==1)
    {
        return 0;
    }
    //1 启动上行线路  启动对串口文件的读取  开辟线程 持续对串口文件执行read 
    pthread_create(&device->read_thread,NULL,app_device_up_read_dev,device);
    //2 启动下行线路  启动对mqtt的读取   向消息队列模块注册真实的回调函数 （推模式）
    app_mqtt_register_callback(app_device_down_mqtt_to_buffer);

    device->is_running=1;

    return 0;
}


int app_device_destroy()
{
    //结束线程
    pthread_cancel(device->read_thread);

    // 释放上下行缓冲
    app_buffer_destroy(device->up_buffer);
    app_buffer_destroy(device->down_buffer);

    // 文件关闭
    close(device->fd);

    // 释放设备结构体
    free(device);

    return 0;

}